Unity上コードで2D Textureを切り出してみた
概要
Unityを使う際、ちゃんとしたTextureがある場合Resource.Load()
で簡単にロードできますが、ネット上のものを使ったりするとき、DemoにTextureをすぐ使いたいときは、コード上でクロップしなければならないこともよくあると思います。
このブログで2D Textureをクロップする方法をメモしたいと思ういます。
やり方
今回の例は、この麻雀牌の画像を元のものとし、麻雀牌を一つずつ切り出したいです。
画像のGithub Link
using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEditor; public class TextureManager : MonoBehaviour { public Texture2D mahjongTileImage; // 元の画像 public List<Texture2D> textureList; // クロップした結果 // ソフト上に確認した各サイズ int bgWidth = 273; // 青い背景を含めた牌の幅 int bgHeight = 217; // 青い背景を含めた牌の高さ int tileWidth = 150; // 牌の幅 int tileHeight = 200; // 牌の高さ int leftDummy = 60; // 最初の左から要らない部分 int bottomDummy = 12; // 最初の下から要らない部分 }
まず、TextureManager : MonoBehaviour
というクラスを作って、上記のメンバーを定義します。
そして、Unity Editorに、mahjongTileImage
に元の映像を指定します。
var assetPath = AssetDatabase.GetAssetPath(mahjongTileImage); var tImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter; tImporter.textureType = TextureImporterType.Default; tImporter.isReadable = true; AssetDatabase.ImportAsset(assetPath); AssetDatabase.Refresh();
元の映像は.png
で直接コードで編集することはできなそうなので、一度isReadable = true
にし、編集できる形にインポートし直します。
textureList = new List<Texture2D>(); int MaxRow = 4; // Suit x 3 rows, Honor x 1 row int MaxColumn = 10; // 9 + special 5 // 実験なので、空の部分と赤牌無視してTextureを切り出したい List<int> tilesToIgnore = new List<int>() { 7, 8, 9, 15, 25, 35 }; // Tempのリストのリスト、「x = 0, y = 0」は左下で、実際ロードする際は「東」からなので、 その後Textureの並び順は「一萬」からにしたい List<List<Texture2D>> tempTexListList = new List<List<Texture2D>>(); ``` 行、列、無視するブロック、一時使うリストのリストを定義します。 ```csharp // Scan all the tile textures from the tiles image for (int row = 0; row < MaxRow; row++) { List<Texture2D> tempTexList = new List<Texture2D>(); for (int column = 0; column < MaxColumn; column++) { // 無視する部分 if (tilesToIgnore.Contains(row * 10 + column)) continue; // GetPixels(x, y, width, height) Color[] pixels = mahjongTileImage.GetPixels(leftDummy + bgWidth * column, bottomDummy + bgHeight * row, tileWidth, tileHeight); Texture2D newTex = new Texture2D(tileWidth, tileHeight); ; newTex.SetPixels(pixels); newTex.Apply(); tempTexList.Add(newTex); } tempTexListList.Add(tempTexList); } // 下からロードするので、「一萬」を最初のTextureにしたので、行の順番を逆にします tempTexListList.Reverse(); foreach (var list in tempTexListList) { // メンバー変数としてのリストに保存します textureList.AddRange(list); }
コードをGameObjectにアタッチして、シーンに入れてから実行すると、Texture予想通りキャッシュされてます。
public Texture2D GetTexture(int tileIndex) { // list.ElementAt()を使うため、System.Linqをインポートしてください return textureList.ElementAt(tileIndex); }
実際Textureを使いたい時、Indexを指定して取れます。
以上です。